extends Area2D
class_name SoulStone

@export var radius: float = 6.0
@export var color: Color = Color(1.0, 0.9, 0.2, 1.0) # 黄色
@export var pickup_group: StringName = &"player"
@export var magnet_speed: float = 240.0
@export var magnet_accel: float = 600.0
var _current_speed: float = 0.0
@export var pickup_catch_radius: float = 6.0
var _is_collecting: bool = false
var _force_magnet: bool = false
var _force_target: Node2D = null
@export var auto_magnet_base_speed: float = 96.0
@export var auto_magnet_accel: float = 1280.0
@export var auto_magnet_max_speed: float = 960.0
var _force_no_bonus: bool = false

func _ready():
	# 延迟初始化，避免物理查询刷新期修改状态
	call_deferred("_deferred_init")
	set_process(true)
	# 加入分组，便于全局拾取
	if not is_in_group("soul_stone"):
		add_to_group("soul_stone")

func _deferred_init() -> void:
	# 碰撞形状
	var cs := CollisionShape2D.new()
	var shape := CircleShape2D.new()
	shape.radius = radius
	cs.shape = shape
	add_child(cs)
	# 视觉绘制
	queue_redraw()
	set_deferred("monitoring", true)
	connect("body_entered", Callable(self, "_on_body_entered"))

func _process(delta: float) -> void:
	# 磁吸逻辑
	var player := get_tree().get_first_node_in_group(pickup_group)
	if player == null and not _force_magnet:
		return
	var target: Node2D = (_force_target if _force_magnet and _force_target != null else player) as Node2D
	if target == null:
		return
	var dist := global_position.distance_to(target.global_position)
	var pickup_r := float(player.get_pickup_radius()) if player and player.has_method("get_pickup_radius") else 30.0
	# 普通模式：进入拾取半径才吸附；强制模式：无条件吸附
	var should_magnet := _force_magnet or (dist <= pickup_r)
	if should_magnet:
		if _force_magnet:
			var new_speed: float = _current_speed + auto_magnet_accel * delta
			if new_speed < auto_magnet_base_speed:
				new_speed = auto_magnet_base_speed
			_current_speed = min(auto_magnet_max_speed, new_speed)
		else:
			_current_speed = min(magnet_speed, _current_speed + magnet_accel * delta)
		var dir: Vector2 = (target.global_position - global_position).normalized()
		global_position += dir * _current_speed * delta
	else:
		_current_speed = 0.0

	# 接触阈值：强制模式用固定捕获半径，普通模式更严格
	var catch_r: float = pickup_catch_radius if _force_magnet else min(pickup_catch_radius, pickup_r * 0.25)
	if dist <= catch_r:
		_on_body_entered(target)

func _draw():
	# 画一颗五角星
	var outer_r := radius
	var inner_r := radius * 0.5
	var pts: PackedVector2Array = []
	for i in range(10):
		var ang := -PI/2 + i * TAU / 10.0
		var r := outer_r if i % 2 == 0 else inner_r
		pts.append(Vector2(cos(ang), sin(ang)) * r)
	# 填充
	draw_colored_polygon(pts, color)
	# 描边（稍深）
	for i in range(pts.size()):
		var a := pts[i]
		var b := pts[(i + 1) % pts.size()]
		draw_line(a, b, Color(color.r * 0.9, color.g * 0.8, 0.0, 1.0), 1.5)

func _on_body_entered(body: Node) -> void:
	# 仅在足够接近玩家中心时才允许拾取
	if not body or not body.is_in_group(pickup_group):
		return
	var dist_to_center := global_position.distance_to((body as Node2D).global_position)
	if dist_to_center > pickup_catch_radius:
		return
	# 正常拾取：根据概率决定获得数量（影响魂石与经验）。回合结束全图吸附禁用加成
	var amount: int = 1
	if not _force_no_bonus:
		amount = _roll_soul_amount()
	_collect_with_tween(body, amount)

## 立即拾取（忽略距离判定），用于回合结束全场收集（带动画）
func collect_now(body: Node) -> void:
	if not body or not body.is_in_group(pickup_group):
		return
	# 回合结束的全场收集：固定只获得1个，不触发概率加成
	_collect_with_tween(body, 1)

## 强制磁吸到玩家（用于回合结束：全图吸附，碰到玩家才算拾取）
func force_magnet_to(body: Node) -> void:
	if body and body is Node2D:
		_force_magnet = true
		_force_no_bonus = true
		_force_target = body as Node2D
		_current_speed = 0.0
		set_process(true)
		set_deferred("monitoring", true)

func _collect_with_tween(body: Node, amount: int) -> void:
	if _is_collecting:
		return
	_is_collecting = true
	# 停止物理与磁吸逻辑，避免过程中再次触发
	set_deferred("monitoring", false)
	set_process(false)
	# 动画：位置吸向玩家，轻微缩放并淡出
	var target := (body as Node2D).global_position
	var tw := create_tween()
	tw.set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_IN_OUT)
	tw.tween_property(self, "global_position", target, 0.35)
	# 视觉效果（如果需要可选）
	var has_scale := true
	var has_modulate := true
	if has_scale:
		tw.parallel().tween_property(self, "scale", Vector2(0.35, 0.35), 0.35)
	if has_modulate:
		tw.parallel().tween_property(self, "modulate:a", 0.0, 0.35)
	# 结束时结算并销毁
	tw.finished.connect(func():
		if body and body.has_method("add_soul_count"):
			body.add_soul_count(max(1, amount))
		# 弹出加成文本
		if amount >= 2:
			var color2 := Color(0.7, 1.0, 0.7) if amount == 2 else Color(0.3, 1.0, 0.3)
			var text := "x" + str(amount)
			var pos := (body as Node2D).global_position + Vector2(randf_range(-20, 20), -30)
			var hint = DamageText.create_custom_text(text, pos, color2, 0.9, 22 if amount == 2 else 24)
			get_tree().current_scene.add_child(hint)
		queue_free()
	)

## 按概率决定一次拾取获得的魂石数量
## 30%=>1, 45%=>2, 25%=>3
func _roll_soul_amount() -> int:
	var r := randf()
	if r < 0.30:
		return 1
	elif r < 0.30 + 0.45:
		return 2
	else:
		return 3
